package cn.mazexal.exambg.utils;

import cn.mazexal.exambg.common.models.UnauthorizedException;
import cn.mazexal.exambg.models.bo.Credentials;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;

/**
 * JWT 令牌提供者
 *
 * @author Lay
 * @date 2024/7/15
 */
@Component
public class JWTProvider {
    /**
     * 密钥
     */
    private final SecretKey key;

    public JWTProvider(@Value("${jwt.secret}") String secret) {
        key = Keys.hmacShaKeyFor(secret.getBytes());
    }

    /**
     * 生成令牌
     *
     * @param credentials 访问凭证
     * @return 令牌
     */
    public String encode(Credentials credentials) {
        return Jwts.builder()
                .signWith(key, Jwts.SIG.HS256)
                .expiration(credentials.getExpireTime())
                .issuedAt(credentials.getIssueTime())
                .id(String.valueOf(credentials.getUserId()))
                .compact();
    }

    /**
     * 解析令牌
     *
     * @param token 令牌
     * @return 访问凭证
     */
    public Credentials decode(String token) {
        // 解析字段
        try {
            Jws<Claims> claimsJws = Jwts.parser()
                    .verifyWith(key)
                    .build()
                    .parseSignedClaims(token);
            Claims claims = claimsJws.getPayload();
            Date issueTime = claims.getIssuedAt();
            Date expireTime = claims.getExpiration();
            Long idUser = Long.parseLong(claims.getId());
            // 构建实体
            return new Credentials(idUser, issueTime, expireTime);
        } catch (Exception ignored) {
            throw new UnauthorizedException();
        }
    }
}